<!DOCTYPE html>
<html>
<head>
	<!-- Global site tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id='UA-133422980-2"></script>
	<script>
	  window.dataLayer = window.dataLayer || [];
	  function gtag(){dataLayer.push(arguments);}
	  gtag('js', new Date());

	  gtag('config', 'UA-133422980-2');
	</script>

	<meta charset="utf-8">
	<meta http-equiv="x-ua-compatible" content="ie=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">

	<title>
		gem5: MSI Directory implementation 
	</title>

	<!-- SITE FAVICON -->
	<link rel="shortcut icon" type="image/gif" href="/assets/img/gem5ColorVert.gif"/>

	<link rel="canonical" href="http://localhost:4000/documentation/learning_gem5/part3/directory/">
	<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,700,800,600' rel='stylesheet' type='text/css'>
	<link href='https://fonts.googleapis.com/css?family=Muli:400,300' rel='stylesheet' type='text/css'>

	<!-- FAVICON -->
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

	<!-- BOOTSTRAP -->
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

	<!-- CUSTOM CSS -->
	<link rel="stylesheet" href="/css/main.css">
</head>


<body>
	<nav class="navbar navbar-expand-md navbar-light bg-light">
  <a class="navbar-brand" href="/">
		<img src="/assets/img/gem5ColorLong.gif" alt="gem5" height=55px>
	</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavDropdown">
    <!-- LIST FOR NAVBAR -->
    <ul class="navbar-nav ml-auto">
      <!-- HOME -->
      <li class="nav-item ">
        <a class="nav-link" href="/">Home</a>
      </li>

      <!-- ABOUT -->
			<li class="nav-item dropdown ">
				<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
					About
				</a>
				<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <a class="dropdown-item" href="/about">About gem5</a>
          <a class="dropdown-item" href="/publications">Publications</a>
          <a class="dropdown-item" href="/governance">Governance</a>
				</div>
			</li>

      <!-- DOCUMENTATION -->
			<li class="nav-item dropdown active">
				<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
					Documentation
				</a>
				<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
					<!-- Pull navigation from _data/documentation.yml -->
					
            <a class="dropdown-item" href="/documentation">gem5 documentation</a>
					
            <a class="dropdown-item" href="/documentation/learning_gem5/introduction">Learning gem5</a>
					
            <a class="dropdown-item" href="http://doxygen.gem5.org/release/current/index.html">gem5 Doxygen</a>
					
            <a class="dropdown-item" href="/documentation/reporting_problems">Reporting Problems</a>
					
				</div>
			</li>

      <!-- EVENTS -->
			<li class="nav-item dropdown ">
        <a class="nav-link" href="/events/">Events</a>
			</li>

      <!-- CONTRIBUTING -->
      <li class="nav-item ">
        <a class="nav-link" href="/contributing">Contributing</a>
      </li>

      <!-- BLOG -->
      <li class="nav-item ">
        <a class="nav-link" href="/blog">Blog</a>
      </li>

      <!-- SEARCH -->
			<li class="nav-item ">
        <a class="nav-link" href="/search">Search</a>
      </li>
    </ul>
  </div>
</nav>

	<main>
		<div class="sidenav-top">
  <div class="sidenav-brand bg-light">
    <a href="/"><img src="/assets/img/gem5ColorLong.gif" height="55px"></a>
  </div>
  <div class="search">
    <form action="/search" method="get">
      <!-- <label for="search-box"><i class="fa fa-search"></i></label> -->
      <input type="text" name="query">
      <button type="submit" name="submit"><i class="fa fa-search"></i></button>
    </form>
  </div>
</div>
<div class="sidenav">
  <!-- Pull navigation from _data/documentation.yml -->
  
    
  
    
    
      <a class="item" href="/documentation/learning_gem5/introduction" role="button" aria-expanded="false" aria-controls="collapseExample">
        Introduction
      </a>
      <div class="collapse " id="introduction">
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part1" role="button" aria-expanded="false" aria-controls="collapseExample">
        Getting Started
      </a>
      <div class="collapse " id="part1">
        
          <a class="subitem " href="/documentation/learning_gem5/part1/building">Building gem5</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/simple_config">Creating a simple configuration script</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/cache_config">Adding cache to configuration script</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/gem5_stats">Understanding gem5 statistics and output</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part1/example_configs">Using the default configuration scripts</a>
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part2" role="button" aria-expanded="false" aria-controls="collapseExample">
        Modifying/Extending
      </a>
      <div class="collapse " id="part2">
        
          <a class="subitem " href="/documentation/learning_gem5/part2/environment">Setting up your development environment</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/helloobject">Creating a very simple SimObject</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/debugging">Debugging gem5</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/events">Event-driven programming</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/parameters">Adding parameters to SimObjects and more events</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/memoryobject">Creating SimObjects in the memory system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part2/simplecache">Creating a simple cache object</a>
        
      </div>
    
      <a class="item" data-toggle="collapse" href="#part3" role="button" aria-expanded="false" aria-controls="collapseExample">
        Modeling Cache Coherence with Ruby
      </a>
      <div class="collapse show" id="part3">
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIintro">Introduction to Ruby</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-intro">MSI example cache protocol</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-declarations">Declaring a state machine</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-in-ports">In port code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-actions">Action code blocks</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/cache-transitions">Transition code blocks</a>
        
          <a class="subitem active" href="/documentation/learning_gem5/part3/directory">MSI Directory implementation</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIbuilding">Compiling a SLICC protocol</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/configuration">Configuring a simple Ruby system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/running">Running the simple Ruby system</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/MSIdebugging">Debugging SLICC Protocols</a>
        
          <a class="subitem " href="/documentation/learning_gem5/part3/simple-MI_example">Configuring for a standard protocol</a>
        
      </div>
    
      <a class="item" href="/documentation/learning_gem5/gem5_101/" role="button" aria-expanded="false" aria-controls="collapseExample">
        gem5 101
      </a>
      <div class="collapse " id="gem5_101">
        
      </div>
    
    
  
    
  
    
  
</div>


<div class="container" id="doc-container">
  <div class="edit"><a href="https://gem5.googlesource.com/public/gem5-website/+/refs/heads/master/README.md">Edit this page</a></div>
  <b>authors:</b> Jason Lowe-Power<br>
  

  <br>
  <h1 id="msi-directory-implementation">MSI Directory implementation</h1>

<p>Implementing a directory controller is very similar to the L1 cache
controller, except using a different state machine table. The state
machine fore the directory can be found in Table 8.2 in Sorin et al.
Since things are mostly similar to the L1 cache, this section mostly
just discusses a few more SLICC details and a few differences between
directory controllers and cache controllers. Let’s dive straight in and
start modifying a new file <code class="highlighter-rouge">MSI-dir.sm</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">machine</span><span class="p">(</span><span class="n">MachineType</span><span class="o">:</span><span class="n">Directory</span><span class="p">,</span> <span class="s">"Directory protocol"</span><span class="p">)</span>
<span class="o">:</span>
  <span class="n">DirectoryMemory</span> <span class="o">*</span> <span class="n">directory</span><span class="p">;</span>
  <span class="n">Cycles</span> <span class="n">toMemLatency</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span>

<span class="n">MessageBuffer</span> <span class="o">*</span><span class="n">forwardToCache</span><span class="p">,</span> <span class="n">network</span><span class="o">=</span><span class="s">"To"</span><span class="p">,</span> <span class="n">virtual_network</span><span class="o">=</span><span class="s">"1"</span><span class="p">,</span>
      <span class="n">vnet_type</span><span class="o">=</span><span class="s">"forward"</span><span class="p">;</span>
<span class="n">MessageBuffer</span> <span class="o">*</span><span class="n">responseToCache</span><span class="p">,</span> <span class="n">network</span><span class="o">=</span><span class="s">"To"</span><span class="p">,</span> <span class="n">virtual_network</span><span class="o">=</span><span class="s">"2"</span><span class="p">,</span>
      <span class="n">vnet_type</span><span class="o">=</span><span class="s">"response"</span><span class="p">;</span>

<span class="n">MessageBuffer</span> <span class="o">*</span><span class="n">requestFromCache</span><span class="p">,</span> <span class="n">network</span><span class="o">=</span><span class="s">"From"</span><span class="p">,</span> <span class="n">virtual_network</span><span class="o">=</span><span class="s">"0"</span><span class="p">,</span>
      <span class="n">vnet_type</span><span class="o">=</span><span class="s">"request"</span><span class="p">;</span>

<span class="n">MessageBuffer</span> <span class="o">*</span><span class="n">responseFromCache</span><span class="p">,</span> <span class="n">network</span><span class="o">=</span><span class="s">"From"</span><span class="p">,</span> <span class="n">virtual_network</span><span class="o">=</span><span class="s">"2"</span><span class="p">,</span>
      <span class="n">vnet_type</span><span class="o">=</span><span class="s">"response"</span><span class="p">;</span>

<span class="n">MessageBuffer</span> <span class="o">*</span><span class="n">responseFromMemory</span><span class="p">;</span>

<span class="p">{</span>
<span class="p">.</span> <span class="p">.</span> <span class="p">.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>First, there are two parameter to this directory controller,
<code class="highlighter-rouge">DirectoryMemory</code> and a <code class="highlighter-rouge">toMemLatency</code>. The <code class="highlighter-rouge">DirectoryMemory</code> is a
little weird. It is allocated at initialization time such that it can
cover <em>all</em> of physical memory, like a complete directory <em>not a
directory cache</em>. I.e., there are pointers in the <code class="highlighter-rouge">DirectoryMemory</code>
object for every 64-byte block in physical memory. However, the actual
entries (as defined below) are lazily created via <code class="highlighter-rouge">getDirEntry()</code>. We’ll
see more details about <code class="highlighter-rouge">DirectoryMemory</code> below.</p>

<p>Next, is the <code class="highlighter-rouge">toMemLatency</code> parameter. This will be used in the
<code class="highlighter-rouge">enqueue</code> function when enqueuing requests to model the directory
latency. We didn’t use a parameter for this in the L1 cache, but it is
simple to make the controller latency parameterized. This parameter
defaults to 1 cycle. It is not required to set a default here. The
default is propagated to the generated SimObject description file as the
default to the SimObject parameter.</p>

<p>Next, we have the message buffers for the directory. Importantly, <em>these
need to have the same virtual network numbers</em> as the message buffers in
the L1 cache. These virtual network numbers are how the Ruby network
directs messages between controllers.</p>

<p>There is also one more special message buffer: <code class="highlighter-rouge">responseFromMemory</code>.
This is similar to the <code class="highlighter-rouge">mandatoryQueue</code>, except instead of being like a
slave port for CPUs it is like a master port. The <code class="highlighter-rouge">responseFromMemory</code>
buffer will deliver response sent across the the memory port, as we will
see below in the action section.</p>

<p>After the parameters and message buffers, we need to declare all of the
states, events, and other local structures.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">state_declaration</span><span class="p">(</span><span class="n">State</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Directory states"</span><span class="p">,</span>
                  <span class="k">default</span><span class="o">=</span><span class="s">"Directory_State_I"</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Stable states.</span>
    <span class="c1">// NOTE: These are "cache-centric" states like in Sorin et al.</span>
    <span class="c1">// However, The access permissions are memory-centric.</span>
    <span class="n">I</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Read_Write</span><span class="p">,</span>  <span class="n">desc</span><span class="o">=</span><span class="s">"Invalid in the caches."</span><span class="p">;</span>
    <span class="n">S</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Read_Only</span><span class="p">,</span>   <span class="n">desc</span><span class="o">=</span><span class="s">"At least one cache has the blk"</span><span class="p">;</span>
    <span class="n">M</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Invalid</span><span class="p">,</span>     <span class="n">desc</span><span class="o">=</span><span class="s">"A cache has the block in M"</span><span class="p">;</span>

    <span class="c1">// Transient states</span>
    <span class="n">S_D</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Busy</span><span class="p">,</span>      <span class="n">desc</span><span class="o">=</span><span class="s">"Moving to S, but need data"</span><span class="p">;</span>

    <span class="c1">// Waiting for data from memory</span>
    <span class="n">S_m</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Read_Write</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"In S waiting for mem"</span><span class="p">;</span>
    <span class="n">M_m</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Read_Write</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Moving to M waiting for mem"</span><span class="p">;</span>

    <span class="c1">// Waiting for write-ack from memory</span>
    <span class="n">MI_m</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Busy</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Moving to I waiting for ack"</span><span class="p">;</span>
    <span class="n">SS_m</span><span class="p">,</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">Busy</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Moving to I waiting for ack"</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">enumeration</span><span class="p">(</span><span class="n">Event</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Directory events"</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Data requests from the cache</span>
    <span class="n">GetS</span><span class="p">,</span>         <span class="n">desc</span><span class="o">=</span><span class="s">"Request for read-only data from cache"</span><span class="p">;</span>
    <span class="n">GetM</span><span class="p">,</span>         <span class="n">desc</span><span class="o">=</span><span class="s">"Request for read-write data from cache"</span><span class="p">;</span>

    <span class="c1">// Writeback requests from the cache</span>
    <span class="n">PutSNotLast</span><span class="p">,</span>  <span class="n">desc</span><span class="o">=</span><span class="s">"PutS and the block has other sharers"</span><span class="p">;</span>
    <span class="n">PutSLast</span><span class="p">,</span>     <span class="n">desc</span><span class="o">=</span><span class="s">"PutS and the block has no other sharers"</span><span class="p">;</span>
    <span class="n">PutMOwner</span><span class="p">,</span>    <span class="n">desc</span><span class="o">=</span><span class="s">"Dirty data writeback from the owner"</span><span class="p">;</span>
    <span class="n">PutMNonOwner</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Dirty data writeback from non-owner"</span><span class="p">;</span>

    <span class="c1">// Cache responses</span>
    <span class="n">Data</span><span class="p">,</span>         <span class="n">desc</span><span class="o">=</span><span class="s">"Response to fwd request with data"</span><span class="p">;</span>

    <span class="c1">// From Memory</span>
    <span class="n">MemData</span><span class="p">,</span>      <span class="n">desc</span><span class="o">=</span><span class="s">"Data from memory"</span><span class="p">;</span>
    <span class="n">MemAck</span><span class="p">,</span>       <span class="n">desc</span><span class="o">=</span><span class="s">"Ack from memory that write is complete"</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">structure</span><span class="p">(</span><span class="n">Entry</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"..."</span><span class="p">,</span> <span class="n">interface</span><span class="o">=</span><span class="s">"AbstractEntry"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">State</span> <span class="n">DirState</span><span class="p">,</span>         <span class="n">desc</span><span class="o">=</span><span class="s">"Directory state"</span><span class="p">;</span>
    <span class="n">NetDest</span> <span class="n">Sharers</span><span class="p">,</span>        <span class="n">desc</span><span class="o">=</span><span class="s">"Sharers for this block"</span><span class="p">;</span>
    <span class="n">NetDest</span> <span class="n">Owner</span><span class="p">,</span>          <span class="n">desc</span><span class="o">=</span><span class="s">"Owner of this block"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In the <code class="highlighter-rouge">state_declaration</code> we define a default. For many things in SLICC
you can specify a default. However, this default must use the C++ name
(mangled SLICC name). For the state below you have to use the controller
name and the name we use for states. In this case, since the name of the
machine is “Directory” the name for “I” is “Directory”+”State” (for the
name of the structure)+”I”.</p>

<p>Note that the permissions in the directory are “memory-centric”.
Whereas, all of the states are cache centric as in Sorin et al.</p>

<p>In the <code class="highlighter-rouge">Entry</code> definition for the directory, we use a NetDest for both
the sharers and the owner. This makes sense for the sharers, since we
want a full bitvector for all L1 caches that may be sharing the block.
The reason we also use a <code class="highlighter-rouge">NetDest</code> for the owner is to simply copy the
structure into the message we send as a response as shown below.</p>

<p>In this implementation, we use a few more transient states than in Table
8.2 in Sorin et al. to deal with the fact that the memory latency in
unknown. In Sorin et al., the authors assume that the directory state
and memory data is stored together in main-memory to simplify the
protocol. Similarly, we also include new actions: the responses from
memory.</p>

<p>Next, we have the functions that need to overridden and declared. The
function <code class="highlighter-rouge">getDirectoryEntry</code> either returns the valid directory entry,
or, if it hasn’t been allocated yet, this allocates the entry.
Implementing it this way may save some host memory since this is lazily
populated.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Tick</span> <span class="nf">clockEdge</span><span class="p">();</span>

<span class="n">Entry</span> <span class="nf">getDirectoryEntry</span><span class="p">(</span><span class="n">Addr</span> <span class="n">addr</span><span class="p">),</span> <span class="n">return_by_pointer</span> <span class="o">=</span> <span class="s">"yes"</span> <span class="p">{</span>
    <span class="n">Entry</span> <span class="n">dir_entry</span> <span class="o">:=</span> <span class="k">static_cast</span><span class="p">(</span><span class="n">Entry</span><span class="p">,</span> <span class="s">"pointer"</span><span class="p">,</span> <span class="n">directory</span><span class="p">[</span><span class="n">addr</span><span class="p">]);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">is_invalid</span><span class="p">(</span><span class="n">dir_entry</span><span class="p">))</span> <span class="p">{</span>
        <span class="c1">// This first time we see this address allocate an entry for it.</span>
        <span class="n">dir_entry</span> <span class="o">:=</span> <span class="k">static_cast</span><span class="p">(</span><span class="n">Entry</span><span class="p">,</span> <span class="s">"pointer"</span><span class="p">,</span>
                                 <span class="n">directory</span><span class="p">.</span><span class="n">allocate</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="k">new</span> <span class="n">Entry</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">dir_entry</span><span class="p">;</span>
<span class="err">}</span>

<span class="n">State</span> <span class="nf">getState</span><span class="p">(</span><span class="n">Addr</span> <span class="n">addr</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">directory</span><span class="p">.</span><span class="n">isPresent</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">DirState</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">State</span><span class="o">:</span><span class="n">I</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">setState</span><span class="p">(</span><span class="n">Addr</span> <span class="n">addr</span><span class="p">,</span> <span class="n">State</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">directory</span><span class="p">.</span><span class="n">isPresent</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">state</span> <span class="o">==</span> <span class="n">State</span><span class="o">:</span><span class="n">M</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">DPRINTF</span><span class="p">(</span><span class="n">RubySlicc</span><span class="p">,</span> <span class="s">"Owner %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">Owner</span><span class="p">);</span>
            <span class="n">assert</span><span class="p">(</span><span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">Owner</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">);</span>
            <span class="n">assert</span><span class="p">(</span><span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">Sharers</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">DirState</span> <span class="o">:=</span> <span class="n">state</span><span class="p">;</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">state</span> <span class="o">==</span> <span class="n">State</span><span class="o">:</span><span class="n">I</span><span class="p">)</span>  <span class="p">{</span>
            <span class="n">assert</span><span class="p">(</span><span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">Owner</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
            <span class="n">assert</span><span class="p">(</span><span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">).</span><span class="n">Sharers</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">AccessPermission</span> <span class="nf">getAccessPermission</span><span class="p">(</span><span class="n">Addr</span> <span class="n">addr</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">directory</span><span class="p">.</span><span class="n">isPresent</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Entry</span> <span class="n">e</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">);</span>
        <span class="k">return</span> <span class="n">Directory_State_to_permission</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">DirState</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span>  <span class="p">{</span>
        <span class="k">return</span> <span class="n">AccessPermission</span><span class="o">:</span><span class="n">NotPresent</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">setAccessPermission</span><span class="p">(</span><span class="n">Addr</span> <span class="n">addr</span><span class="p">,</span> <span class="n">State</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">directory</span><span class="p">.</span><span class="n">isPresent</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Entry</span> <span class="n">e</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">addr</span><span class="p">);</span>
        <span class="n">e</span><span class="p">.</span><span class="n">changePermission</span><span class="p">(</span><span class="n">Directory_State_to_permission</span><span class="p">(</span><span class="n">state</span><span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">functionalRead</span><span class="p">(</span><span class="n">Addr</span> <span class="n">addr</span><span class="p">,</span> <span class="n">Packet</span> <span class="o">*</span><span class="n">pkt</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">functionalMemoryRead</span><span class="p">(</span><span class="n">pkt</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">functionalWrite</span><span class="p">(</span><span class="n">Addr</span> <span class="n">addr</span><span class="p">,</span> <span class="n">Packet</span> <span class="o">*</span><span class="n">pkt</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">functionalMemoryWrite</span><span class="p">(</span><span class="n">pkt</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>Next, we need to implement the ports for the cache. First we specify the
<code class="highlighter-rouge">out_port</code> and then the <code class="highlighter-rouge">in_port</code> code blocks. The only difference
between the <code class="highlighter-rouge">in_port</code> in the directory and in the L1 cache is that the
directory does not have a TBE or cache entry. Thus, we do not pass
either into the <code class="highlighter-rouge">trigger</code> function.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">out_port</span><span class="p">(</span><span class="n">forward_out</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="n">forwardToCache</span><span class="p">);</span>
<span class="n">out_port</span><span class="p">(</span><span class="n">response_out</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">,</span> <span class="n">responseToCache</span><span class="p">);</span>

<span class="n">in_port</span><span class="p">(</span><span class="n">memQueue_in</span><span class="p">,</span> <span class="n">MemoryMsg</span><span class="p">,</span> <span class="n">responseFromMemory</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">memQueue_in</span><span class="p">.</span><span class="n">isReady</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">()))</span> <span class="p">{</span>
        <span class="n">peek</span><span class="p">(</span><span class="n">memQueue_in</span><span class="p">,</span> <span class="n">MemoryMsg</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">MemoryRequestType</span><span class="o">:</span><span class="n">MEMORY_READ</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">MemData</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">MemoryRequestType</span><span class="o">:</span><span class="n">MEMORY_WB</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">MemAck</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="n">error</span><span class="p">(</span><span class="s">"Invalid message"</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">in_port</span><span class="p">(</span><span class="n">response_in</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">,</span> <span class="n">responseFromCache</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">response_in</span><span class="p">.</span><span class="n">isReady</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">()))</span> <span class="p">{</span>
        <span class="n">peek</span><span class="p">(</span><span class="n">response_in</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">Data</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">Data</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="n">error</span><span class="p">(</span><span class="s">"Unexpected message type."</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">in_port</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="n">requestFromCache</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">request_in</span><span class="p">.</span><span class="n">isReady</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">()))</span> <span class="p">{</span>
        <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">Entry</span> <span class="n">e</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">GetS</span><span class="p">)</span> <span class="p">{</span>

                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">GetS</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">GetM</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">GetM</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">PutS</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">assert</span><span class="p">(</span><span class="n">is_valid</span><span class="p">(</span><span class="n">e</span><span class="p">));</span>
                <span class="c1">// If there is only a single sharer (i.e., the requestor)</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">Sharers</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">assert</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">Sharers</span><span class="p">.</span><span class="n">isElement</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">));</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">PutSLast</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">PutSNotLast</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">==</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">PutM</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">assert</span><span class="p">(</span><span class="n">is_valid</span><span class="p">(</span><span class="n">e</span><span class="p">));</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">Owner</span><span class="p">.</span><span class="n">isElement</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">))</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">PutMOwner</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">trigger</span><span class="p">(</span><span class="n">Event</span><span class="o">:</span><span class="n">PutMNonOwner</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">addr</span><span class="p">);</span>
                <span class="p">}</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="n">error</span><span class="p">(</span><span class="s">"Unexpected message type."</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The next part of the state machine file is the actions. First, we define
actions for queuing memory reads and writes. For this, we will use a
special function define in the <code class="highlighter-rouge">AbstractController</code>: <code class="highlighter-rouge">queueMemoryRead</code>.
This function takes an address and converts it to a gem5 request and
packet and sends it to across the port that is connected to this
controller. We will see how to connect this port in the
configuration section &lt;MSI-config-section&gt;. Note that we need two
different actions to send data to memory for both requests and responses
since there are two different message buffers (virtual networks) that
data might arrive on.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">action</span><span class="p">(</span><span class="n">sendMemRead</span><span class="p">,</span> <span class="s">"r"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Send a memory read request"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">queueMemoryRead</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="n">toMemLatency</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">sendDataToMem</span><span class="p">,</span> <span class="s">"w"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Write data to memory"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">RubySlicc</span><span class="p">,</span> <span class="s">"Writing memory for %#x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">address</span><span class="p">);</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">RubySlicc</span><span class="p">,</span> <span class="s">"Writing %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">DataBlk</span><span class="p">);</span>
        <span class="n">queueMemoryWrite</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="n">toMemLatency</span><span class="p">,</span>
                         <span class="n">in_msg</span><span class="p">.</span><span class="n">DataBlk</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">sendRespDataToMem</span><span class="p">,</span> <span class="s">"rw"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Write data to memory from resp"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">response_in</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">RubySlicc</span><span class="p">,</span> <span class="s">"Writing memory for %#x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">address</span><span class="p">);</span>
        <span class="n">DPRINTF</span><span class="p">(</span><span class="n">RubySlicc</span><span class="p">,</span> <span class="s">"Writing %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">DataBlk</span><span class="p">);</span>
        <span class="n">queueMemoryWrite</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Sender</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="n">toMemLatency</span><span class="p">,</span>
                         <span class="n">in_msg</span><span class="p">.</span><span class="n">DataBlk</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In this code, we also see the last way to add debug information to SLICC
protocols: <code class="highlighter-rouge">DPRINTF</code>. This is exactly the same as a <code class="highlighter-rouge">DPRINTF</code> in gem5,
except in SLICC only the <code class="highlighter-rouge">RubySlicc</code> debug flag is available.</p>

<p>Next, we specify actions to update the sharers and owner of a particular
block.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">action</span><span class="p">(</span><span class="n">addReqToSharers</span><span class="p">,</span> <span class="s">"aS"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Add requestor to sharer list"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Sharers</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">setOwner</span><span class="p">,</span> <span class="s">"sO"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Set the owner"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Owner</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">addOwnerToSharers</span><span class="p">,</span> <span class="s">"oS"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Add the owner to sharers"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Entry</span> <span class="n">e</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">);</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">Owner</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">);</span>
    <span class="n">e</span><span class="p">.</span><span class="n">Sharers</span><span class="p">.</span><span class="n">addNetDest</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">Owner</span><span class="p">);</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">removeReqFromSharers</span><span class="p">,</span> <span class="s">"rS"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Remove requestor from sharers"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Sharers</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">clearSharers</span><span class="p">,</span> <span class="s">"cS"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Clear the sharer list"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Sharers</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">clearOwner</span><span class="p">,</span> <span class="s">"cO"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Clear the owner"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Owner</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The next set of actions send invalidates and forward requests to caches
that the directory cannot deal with alone.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">action</span><span class="p">(</span><span class="n">sendInvToSharers</span><span class="p">,</span> <span class="s">"i"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Send invalidate to all sharers"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">enqueue</span><span class="p">(</span><span class="n">forward_out</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">addr</span> <span class="o">:=</span> <span class="n">address</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">:=</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">Inv</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Requestor</span> <span class="o">:=</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Destination</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Sharers</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">MessageSize</span> <span class="o">:=</span> <span class="n">MessageSizeType</span><span class="o">:</span><span class="n">Control</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">sendFwdGetS</span><span class="p">,</span> <span class="s">"fS"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Send forward getS to owner"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Owner</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">);</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">enqueue</span><span class="p">(</span><span class="n">forward_out</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">addr</span> <span class="o">:=</span> <span class="n">address</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">:=</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">GetS</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Requestor</span> <span class="o">:=</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Destination</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Owner</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">MessageSize</span> <span class="o">:=</span> <span class="n">MessageSizeType</span><span class="o">:</span><span class="n">Control</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">sendFwdGetM</span><span class="p">,</span> <span class="s">"fM"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Send forward getM to owner"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">assert</span><span class="p">(</span><span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Owner</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">);</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">enqueue</span><span class="p">(</span><span class="n">forward_out</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">addr</span> <span class="o">:=</span> <span class="n">address</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">:=</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">GetM</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Requestor</span> <span class="o">:=</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Destination</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">).</span><span class="n">Owner</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">MessageSize</span> <span class="o">:=</span> <span class="n">MessageSizeType</span><span class="o">:</span><span class="n">Control</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Now we have responses from the directory. Here we are peeking into the
special buffer <code class="highlighter-rouge">responseFromMemory</code>. You can find the definition of
<code class="highlighter-rouge">MemoryMsg</code> in <code class="highlighter-rouge">src/mem/protocol/RubySlicc_MemControl.sm</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">action</span><span class="p">(</span><span class="n">sendDataToReq</span><span class="p">,</span> <span class="s">"d"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Send data from memory to requestor. May need to send sharer number, too"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">memQueue_in</span><span class="p">,</span> <span class="n">MemoryMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">enqueue</span><span class="p">(</span><span class="n">response_out</span><span class="p">,</span> <span class="n">ResponseMsg</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">addr</span> <span class="o">:=</span> <span class="n">address</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">:=</span> <span class="n">CoherenceResponseType</span><span class="o">:</span><span class="n">Data</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Sender</span> <span class="o">:=</span> <span class="n">machineID</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Destination</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">OriginalRequestorMachId</span><span class="p">);</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">DataBlk</span> <span class="o">:=</span> <span class="n">in_msg</span><span class="p">.</span><span class="n">DataBlk</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">MessageSize</span> <span class="o">:=</span> <span class="n">MessageSizeType</span><span class="o">:</span><span class="n">Data</span><span class="p">;</span>
            <span class="n">Entry</span> <span class="n">e</span> <span class="o">:=</span> <span class="n">getDirectoryEntry</span><span class="p">(</span><span class="n">address</span><span class="p">);</span>
            <span class="c1">// Only need to include acks if we are the owner.</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">Owner</span><span class="p">.</span><span class="n">isElement</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">OriginalRequestorMachId</span><span class="p">))</span> <span class="p">{</span>
                <span class="n">out_msg</span><span class="p">.</span><span class="n">Acks</span> <span class="o">:=</span> <span class="n">e</span><span class="p">.</span><span class="n">Sharers</span><span class="p">.</span><span class="n">count</span><span class="p">();</span>
            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                <span class="n">out_msg</span><span class="p">.</span><span class="n">Acks</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="n">assert</span><span class="p">(</span><span class="n">out_msg</span><span class="p">.</span><span class="n">Acks</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">sendPutAck</span><span class="p">,</span> <span class="s">"a"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Send the put ack"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">peek</span><span class="p">(</span><span class="n">request_in</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">enqueue</span><span class="p">(</span><span class="n">forward_out</span><span class="p">,</span> <span class="n">RequestMsg</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">addr</span> <span class="o">:=</span> <span class="n">address</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Type</span> <span class="o">:=</span> <span class="n">CoherenceRequestType</span><span class="o">:</span><span class="n">PutAck</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Requestor</span> <span class="o">:=</span> <span class="n">machineID</span><span class="p">;</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">Destination</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">in_msg</span><span class="p">.</span><span class="n">Requestor</span><span class="p">);</span>
            <span class="n">out_msg</span><span class="p">.</span><span class="n">MessageSize</span> <span class="o">:=</span> <span class="n">MessageSizeType</span><span class="o">:</span><span class="n">Control</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Then, we have the queue management and stall actions.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">action</span><span class="p">(</span><span class="n">popResponseQueue</span><span class="p">,</span> <span class="s">"pR"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Pop the response queue"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">response_in</span><span class="p">.</span><span class="n">dequeue</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">());</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">popRequestQueue</span><span class="p">,</span> <span class="s">"pQ"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Pop the request queue"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">request_in</span><span class="p">.</span><span class="n">dequeue</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">());</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">popMemQueue</span><span class="p">,</span> <span class="s">"pM"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Pop the memory queue"</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">memQueue_in</span><span class="p">.</span><span class="n">dequeue</span><span class="p">(</span><span class="n">clockEdge</span><span class="p">());</span>
<span class="p">}</span>

<span class="n">action</span><span class="p">(</span><span class="n">stall</span><span class="p">,</span> <span class="s">"z"</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s">"Stall the incoming request"</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Do nothing.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Finally, we have the transition section of the state machine file. These
mostly come from Table 8.2 in Sorin et al., but there are some extra
transitions to deal with the unknown memory latency.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">transition</span><span class="p">({</span><span class="n">I</span><span class="p">,</span> <span class="n">S</span><span class="p">},</span> <span class="n">GetS</span><span class="p">,</span> <span class="n">S_m</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendMemRead</span><span class="p">;</span>
    <span class="n">addReqToSharers</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">I</span><span class="p">,</span> <span class="p">{</span><span class="n">PutSNotLast</span><span class="p">,</span> <span class="n">PutSLast</span><span class="p">,</span> <span class="n">PutMNonOwner</span><span class="p">})</span> <span class="p">{</span>
    <span class="n">sendPutAck</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">S_m</span><span class="p">,</span> <span class="n">MemData</span><span class="p">,</span> <span class="n">S</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendDataToReq</span><span class="p">;</span>
    <span class="n">popMemQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">I</span><span class="p">,</span> <span class="n">GetM</span><span class="p">,</span> <span class="n">M_m</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendMemRead</span><span class="p">;</span>
    <span class="n">setOwner</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">M_m</span><span class="p">,</span> <span class="n">MemData</span><span class="p">,</span> <span class="n">M</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendDataToReq</span><span class="p">;</span>
    <span class="n">clearSharers</span><span class="p">;</span> <span class="c1">// NOTE: This isn't *required* in some cases.</span>
    <span class="n">popMemQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">S</span><span class="p">,</span> <span class="n">GetM</span><span class="p">,</span> <span class="n">M_m</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendMemRead</span><span class="p">;</span>
    <span class="n">removeReqFromSharers</span><span class="p">;</span>
    <span class="n">sendInvToSharers</span><span class="p">;</span>
    <span class="n">setOwner</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">({</span><span class="n">S</span><span class="p">,</span> <span class="n">S_D</span><span class="p">,</span> <span class="n">SS_m</span><span class="p">,</span> <span class="n">S_m</span><span class="p">},</span> <span class="p">{</span><span class="n">PutSNotLast</span><span class="p">,</span> <span class="n">PutMNonOwner</span><span class="p">})</span> <span class="p">{</span>
    <span class="n">removeReqFromSharers</span><span class="p">;</span>
    <span class="n">sendPutAck</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">S</span><span class="p">,</span> <span class="n">PutSLast</span><span class="p">,</span> <span class="n">I</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">removeReqFromSharers</span><span class="p">;</span>
    <span class="n">sendPutAck</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">M</span><span class="p">,</span> <span class="n">GetS</span><span class="p">,</span> <span class="n">S_D</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendFwdGetS</span><span class="p">;</span>
    <span class="n">addReqToSharers</span><span class="p">;</span>
    <span class="n">addOwnerToSharers</span><span class="p">;</span>
    <span class="n">clearOwner</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">M</span><span class="p">,</span> <span class="n">GetM</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendFwdGetM</span><span class="p">;</span>
    <span class="n">clearOwner</span><span class="p">;</span>
    <span class="n">setOwner</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">({</span><span class="n">M</span><span class="p">,</span> <span class="n">M_m</span><span class="p">,</span> <span class="n">MI_m</span><span class="p">},</span> <span class="p">{</span><span class="n">PutSNotLast</span><span class="p">,</span> <span class="n">PutSLast</span><span class="p">,</span> <span class="n">PutMNonOwner</span><span class="p">})</span> <span class="p">{</span>
    <span class="n">sendPutAck</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">M</span><span class="p">,</span> <span class="n">PutMOwner</span><span class="p">,</span> <span class="n">MI_m</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendDataToMem</span><span class="p">;</span>
    <span class="n">clearOwner</span><span class="p">;</span>
    <span class="n">sendPutAck</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">MI_m</span><span class="p">,</span> <span class="n">MemAck</span><span class="p">,</span> <span class="n">I</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">popMemQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">S_D</span><span class="p">,</span> <span class="p">{</span><span class="n">GetS</span><span class="p">,</span> <span class="n">GetM</span><span class="p">})</span> <span class="p">{</span>
    <span class="n">stall</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">S_D</span><span class="p">,</span> <span class="n">PutSLast</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">removeReqFromSharers</span><span class="p">;</span>
    <span class="n">sendPutAck</span><span class="p">;</span>
    <span class="n">popRequestQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">S_D</span><span class="p">,</span> <span class="n">Data</span><span class="p">,</span> <span class="n">SS_m</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sendRespDataToMem</span><span class="p">;</span>
    <span class="n">popResponseQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">transition</span><span class="p">(</span><span class="n">SS_m</span><span class="p">,</span> <span class="n">MemAck</span><span class="p">,</span> <span class="n">S</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">popMemQueue</span><span class="p">;</span>
<span class="p">}</span>

<span class="c1">// If we get another request for a block that's waiting on memory,</span>
<span class="c1">// stall that request.</span>
<span class="n">transition</span><span class="p">({</span><span class="n">MI_m</span><span class="p">,</span> <span class="n">SS_m</span><span class="p">,</span> <span class="n">S_m</span><span class="p">,</span> <span class="n">M_m</span><span class="p">},</span> <span class="p">{</span><span class="n">GetS</span><span class="p">,</span> <span class="n">GetM</span><span class="p">})</span> <span class="p">{</span>
    <span class="n">stall</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>You can download the complete <code class="highlighter-rouge">MSI-dir.sm</code> file
<a href="/_pages/static/scripts/part3/MSI_protocol/MSI-dir.sm">here</a>.</p>

  <br>

  <!-- RETRIVE PREVIOUS PAGE LINK -->
  
    
  
    
  
    
  
    
  

  <!-- RETRIEVE NEXT PAGE LINK -->
  
    
  
    
  
    
  
    
  


  <div class="navbuttons">
    
      <a href=""><button type="button" class="btn btn-outline-primary">PREVIOUS</button></a>
    

    
      <a href=""><button type="button" class="btn btn-outline-primary">NEXT</button></a>
    
  </div>
</div>

	</main>
	<footer class="page-footer">
	<div class="container">
		<div class="row">

			<div class="col-12 col-sm-4">
				<p>gem5</p>
				<p><a href="/about">About</a></p>
				<p><a href="/publications">Publications</a></p>
				<p><a href="/contributing">Contributing</a></p>
				<p><a href="/governance">Governance</a></p>
			<br></div>

			<div class="col-12 col-sm-4">
				<p>Docs</p>
				<p><a href="/documentation">Documentation</a></p>
				<p><a href="http://gem5.org/Documentation">Old Documentation</a></p>
				<p><a href="https://gem5.googlesource.com/public/gem5">Source</a></p>
			<br></div>

			<div class="col-12 col-sm-4">
				<p>Help</p>
				<p><a href="/search">Search</a></p>
				<p><a href="/mailing_lists">Mailing Lists</a></p>
				<p><a href="https://gem5.googlesource.com/public/gem5-website/+/refs/heads/master/README.md">Website Source</a></p>
			<br></div>

		</div>
	</div>
</footer>


	<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
	<script src="https://unpkg.com/commentbox.io/dist/commentBox.min.js"></script>

	<script>
	  // When the user scrolls down 20px from the top of the document, show the button
	  window.onscroll = function() {scrollFunction()};

	  function scrollFunction() {
	      if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 20) {
	          document.getElementById("myBtn").style.display = "block";
	      } else {
	          document.getElementById("myBtn").style.display = "none";
	      }
	  }

	  // When the user clicks on the button, scroll to the top of the document
	  function topFunction() {
	      document.body.scrollTop = 0;
	      document.documentElement.scrollTop = 0;
	  }

		import commentBox from 'commentbox.io';
		// or
		const commentBox = require('commentbox.io');
		// or if using the CDN, it will be available as a global "commentBox" variable.

		commentBox('my-project-id');

	</script>

</body>


</html>
